search.js ➔ SearchBox   F
last analyzed

Complexity

Conditions 51

Size

Total Lines 341
Code Lines 218

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 51
eloc 218
c 0
b 0
f 0
dl 0
loc 341
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like search.js ➔ SearchBox often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
function convertToId(search)
2
{
3
  var result = '';
4
  for (i=0;i<search.length;i++)
0 ignored issues
show
Bug introduced by
The variable i seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.i.
Loading history...
5
  {
6
    var c = search.charAt(i);
7
    var cn = c.charCodeAt(0);
8
    if (c.match(/[a-z0-9\u0080-\uFFFF]/))
9
    {
10
      result+=c;
11
    }
12
    else if (cn<16)
13
    {
14
      result+="_0"+cn.toString(16);
15
    }
16
    else
17
    {
18
      result+="_"+cn.toString(16);
19
    }
20
  }
21
  return result;
22
}
23
24
function getXPos(item)
25
{
26
  var x = 0;
27
  if (item.offsetWidth)
28
  {
29
    while (item && item!=document.body)
30
    {
31
      x   += item.offsetLeft;
32
      item = item.offsetParent;
33
    }
34
  }
35
  return x;
36
}
37
38
function getYPos(item)
39
{
40
  var y = 0;
41
  if (item.offsetWidth)
42
  {
43
     while (item && item!=document.body)
44
     {
45
       y   += item.offsetTop;
46
       item = item.offsetParent;
47
     }
48
  }
49
  return y;
50
}
51
52
/* A class handling everything associated with the search panel.
53
54
   Parameters:
55
   name - The name of the global variable that will be
56
          storing this instance.  Is needed to be able to set timeouts.
57
   resultPath - path to use for external files
58
*/
59
function SearchBox(name, resultsPath, inFrame, label)
60
{
61
  if (!name || !resultsPath) {  alert("Missing parameters to SearchBox."); }
0 ignored issues
show
Debugging Code Best Practice introduced by
The alert UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
62
63
  // ---------- Instance variables
64
  this.name                  = name;
65
  this.resultsPath           = resultsPath;
66
  this.keyTimeout            = 0;
67
  this.keyTimeoutLength      = 500;
68
  this.closeSelectionTimeout = 300;
69
  this.lastSearchValue       = "";
70
  this.lastResultsPage       = "";
71
  this.hideTimeout           = 0;
72
  this.searchIndex           = 0;
73
  this.searchActive          = false;
74
  this.insideFrame           = inFrame;
75
  this.searchLabel           = label;
76
77
  // ----------- DOM Elements
78
79
  this.DOMSearchField = function()
80
  {  return document.getElementById("MSearchField");  };
81
82
  this.DOMSearchSelect = function()
83
  {  return document.getElementById("MSearchSelect");  };
84
85
  this.DOMSearchSelectWindow = function()
86
  {  return document.getElementById("MSearchSelectWindow");  };
87
88
  this.DOMPopupSearchResults = function()
89
  {  return document.getElementById("MSearchResults");  };
90
91
  this.DOMPopupSearchResultsWindow = function()
92
  {  return document.getElementById("MSearchResultsWindow");  };
93
94
  this.DOMSearchClose = function()
95
  {  return document.getElementById("MSearchClose"); };
96
97
  this.DOMSearchBox = function()
98
  {  return document.getElementById("MSearchBox");  };
99
100
  // ------------ Event Handlers
101
102
  // Called when focus is added or removed from the search field.
103
  this.OnSearchFieldFocus = function(isActive)
104
  {
105
    this.Activate(isActive);
106
  };
107
108
  this.OnSearchSelectShow = function()
109
  {
110
    var searchSelectWindow = this.DOMSearchSelectWindow();
111
    var searchField        = this.DOMSearchSelect();
112
113
    if (this.insideFrame)
114
    {
115
      var left = getXPos(searchField);
116
      var top  = getYPos(searchField);
117
      left += searchField.offsetWidth + 6;
118
      top += searchField.offsetHeight;
119
120
      // show search selection popup
121
      searchSelectWindow.style.display='block';
122
      left -= searchSelectWindow.offsetWidth;
123
      searchSelectWindow.style.left =  left + 'px';
124
      searchSelectWindow.style.top  =  top  + 'px';
125
    }
126
    else
127
    {
128
      var left = getXPos(searchField);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable left already seems to be declared on line 115. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
129
      var top  = getYPos(searchField);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable top already seems to be declared on line 116. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
130
      top += searchField.offsetHeight;
131
132
      // show search selection popup
133
      searchSelectWindow.style.display='block';
134
      searchSelectWindow.style.left =  left + 'px';
135
      searchSelectWindow.style.top  =  top  + 'px';
136
    }
137
138
    // stop selection hide timer
139
    if (this.hideTimeout)
140
    {
141
      clearTimeout(this.hideTimeout);
142
      this.hideTimeout=0;
143
    }
144
    return false; // to avoid "image drag" default event
145
  };
146
147
  this.OnSearchSelectHide = function()
148
  {
149
    this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
150
                                  this.closeSelectionTimeout);
151
  };
152
153
  // Called when the content of the search field is changed.
154
  this.OnSearchFieldChange = function(evt)
155
  {
156
    if (this.keyTimeout) // kill running timer
157
    {
158
      clearTimeout(this.keyTimeout);
159
      this.keyTimeout = 0;
160
    }
161
162
    var e  = (evt) ? evt : window.event; // for IE
163
    if (e.keyCode==40 || e.keyCode==13)
164
    {
165
      if (e.shiftKey==1)
0 ignored issues
show
Best Practice introduced by
Comparing e.shiftKey to 1 using the == operator is not safe. Consider using === instead.
Loading history...
166
      {
167
        this.OnSearchSelectShow();
168
        var win=this.DOMSearchSelectWindow();
169
        for (i=0;i<win.childNodes.length;i++)
0 ignored issues
show
Bug introduced by
The variable i seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.i.
Loading history...
170
        {
171
          var child = win.childNodes[i]; // get span within a
172
          if (child.className=='SelectItem')
173
          {
174
            child.focus();
175
            return;
176
          }
177
        }
178
        return;
179
      }
180
      else if (window.frames.MSearchResults.searchResults)
181
      {
182
        var elem = window.frames.MSearchResults.searchResults.NavNext(0);
183
        if (elem) elem.focus();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
184
      }
185
    }
186
    else if (e.keyCode==27) // Escape out of the search field
187
    {
188
      this.DOMSearchField().blur();
189
      this.DOMPopupSearchResultsWindow().style.display = 'none';
190
      this.DOMSearchClose().style.display = 'none';
191
      this.lastSearchValue = '';
192
      this.Activate(false);
193
      return;
194
    }
195
196
    // strip whitespaces
197
    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
198
199
    if (searchValue != this.lastSearchValue) // search value has changed
200
    {
201
      if (searchValue != "") // non-empty search
202
      {
203
        // set timer for search update
204
        this.keyTimeout = setTimeout(this.name + '.Search()',
205
                                     this.keyTimeoutLength);
206
      }
207
      else // empty search field
208
      {
209
        this.DOMPopupSearchResultsWindow().style.display = 'none';
210
        this.DOMSearchClose().style.display = 'none';
211
        this.lastSearchValue = '';
212
      }
213
    }
214
  };
215
216
  this.SelectItemCount = function(id)
0 ignored issues
show
Unused Code introduced by
The parameter id is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
217
  {
218
    var count=0;
219
    var win=this.DOMSearchSelectWindow();
220
    for (i=0;i<win.childNodes.length;i++)
0 ignored issues
show
Bug introduced by
The variable i seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.i.
Loading history...
221
    {
222
      var child = win.childNodes[i]; // get span within a
223
      if (child.className=='SelectItem')
224
      {
225
        count++;
226
      }
227
    }
228
    return count;
229
  };
230
231
  this.SelectItemSet = function(id)
232
  {
233
    var i,j=0;
234
    var win=this.DOMSearchSelectWindow();
235
    for (i=0;i<win.childNodes.length;i++)
236
    {
237
      var child = win.childNodes[i]; // get span within a
238
      if (child.className=='SelectItem')
239
      {
240
        var node = child.firstChild;
241
        if (j==id)
242
        {
243
          node.innerHTML='&#8226;';
244
        }
245
        else
246
        {
247
          node.innerHTML='&#160;';
248
        }
249
        j++;
250
      }
251
    }
252
  };
253
254
  // Called when an search filter selection is made.
255
  // set item with index id as the active item
256
  this.OnSelectItem = function(id)
257
  {
258
    this.searchIndex = id;
259
    this.SelectItemSet(id);
260
    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
261
    if (searchValue!="" && this.searchActive) // something was found -> do a search
262
    {
263
      this.Search();
264
    }
265
  };
266
267
  this.OnSearchSelectKey = function(evt)
268
  {
269
    var e = (evt) ? evt : window.event; // for IE
270
    if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
271
    {
272
      this.searchIndex++;
273
      this.OnSelectItem(this.searchIndex);
274
    }
275
    else if (e.keyCode==38 && this.searchIndex>0) // Up
276
    {
277
      this.searchIndex--;
278
      this.OnSelectItem(this.searchIndex);
279
    }
280
    else if (e.keyCode==13 || e.keyCode==27)
281
    {
282
      this.OnSelectItem(this.searchIndex);
283
      this.CloseSelectionWindow();
284
      this.DOMSearchField().focus();
285
    }
286
    return false;
287
  };
288
289
  // --------- Actions
290
291
  // Closes the results window.
292
  this.CloseResultsWindow = function()
293
  {
294
    this.DOMPopupSearchResultsWindow().style.display = 'none';
295
    this.DOMSearchClose().style.display = 'none';
296
    this.Activate(false);
297
  };
298
299
  this.CloseSelectionWindow = function()
300
  {
301
    this.DOMSearchSelectWindow().style.display = 'none';
302
  };
303
304
  // Performs a search.
305
  this.Search = function()
306
  {
307
    this.keyTimeout = 0;
308
309
    // strip leading whitespace
310
    var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
311
312
    var code = searchValue.toLowerCase().charCodeAt(0);
313
    var idxChar = searchValue.substr(0, 1).toLowerCase();
314
    if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
315
    {
316
      idxChar = searchValue.substr(0, 2);
317
    }
318
319
    var resultsPage;
320
    var resultsPageWithSearch;
321
    var hasResultsPage;
322
323
    var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
0 ignored issues
show
Bug introduced by
The variable indexSectionsWithContent seems to be never declared. If this is a global, consider adding a /** global: indexSectionsWithContent */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
324
    if (idx!=-1)
325
    {
326
       var hexCode=idx.toString(16);
327
       resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
0 ignored issues
show
Bug introduced by
The variable indexSectionNames seems to be never declared. If this is a global, consider adding a /** global: indexSectionNames */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
328
       resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
329
       hasResultsPage = true;
0 ignored issues
show
Unused Code introduced by
The variable hasResultsPage seems to be never used. Consider removing it.
Loading history...
330
    }
331
    else // nothing available for this search term
332
    {
333
       resultsPage = this.resultsPath + '/nomatches.html';
334
       resultsPageWithSearch = resultsPage;
335
       hasResultsPage = false;
336
    }
337
338
    window.frames.MSearchResults.location = resultsPageWithSearch;
339
    var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
340
341
    if (domPopupSearchResultsWindow.style.display!='block')
342
    {
343
       var domSearchBox = this.DOMSearchBox();
344
       this.DOMSearchClose().style.display = 'inline';
345
       if (this.insideFrame)
346
       {
347
         var domPopupSearchResults = this.DOMPopupSearchResults();
348
         domPopupSearchResultsWindow.style.position = 'relative';
349
         domPopupSearchResultsWindow.style.display  = 'block';
350
         var width = document.body.clientWidth - 8; // the -8 is for IE :-(
351
         domPopupSearchResultsWindow.style.width    = width + 'px';
352
         domPopupSearchResults.style.width          = width + 'px';
353
       }
354
       else
355
       {
356
         var domPopupSearchResults = this.DOMPopupSearchResults();
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable domPopupSearchResults already seems to be declared on line 347. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
357
         var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
358
         var top  = getYPos(domSearchBox) + 20;  // domSearchBox.offsetHeight + 1;
359
         domPopupSearchResultsWindow.style.display = 'block';
360
         left -= domPopupSearchResults.offsetWidth;
361
         domPopupSearchResultsWindow.style.top     = top  + 'px';
362
         domPopupSearchResultsWindow.style.left    = left + 'px';
363
       }
364
    }
365
366
    this.lastSearchValue = searchValue;
367
    this.lastResultsPage = resultsPage;
368
  };
369
370
  // -------- Activation Functions
371
372
  // Activates or deactivates the search panel, resetting things to
373
  // their default values if necessary.
374
  this.Activate = function(isActive)
375
  {
376
    if (isActive || // open it
377
        this.DOMPopupSearchResultsWindow().style.display == 'block'
378
       )
379
    {
380
      this.DOMSearchBox().className = 'MSearchBoxActive';
381
382
      var searchField = this.DOMSearchField();
383
384
      if (searchField.value == this.searchLabel) // clear "Search" term upon entry
385
      {
386
        searchField.value = '';
387
        this.searchActive = true;
388
      }
389
    }
390
    else if (!isActive) // directly remove the panel
391
    {
392
      this.DOMSearchBox().className = 'MSearchBoxInactive';
393
      this.DOMSearchField().value   = this.searchLabel;
394
      this.searchActive             = false;
395
      this.lastSearchValue          = '';
396
      this.lastResultsPage          = '';
397
    }
398
  }
399
}
400
401
// -----------------------------------------------------------------------
402
403
// The class that handles everything on the search results page.
404
function SearchResults(name)
0 ignored issues
show
Unused Code introduced by
The parameter name is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
405
{
406
    // The number of matches from the last run of <Search()>.
407
    this.lastMatchCount = 0;
408
    this.lastKey = 0;
409
    this.repeatOn = false;
410
411
    // Toggles the visibility of the passed element ID.
412
    this.FindChildElement = function(id)
413
    {
414
      var parentElement = document.getElementById(id);
415
      var element = parentElement.firstChild;
416
417
      while (element && element!=parentElement)
418
      {
419
        if (element.nodeName == 'DIV' && element.className == 'SRChildren')
420
        {
421
          return element;
422
        }
423
424
        if (element.nodeName == 'DIV' && element.hasChildNodes())
425
        {
426
           element = element.firstChild;
427
        }
428
        else if (element.nextSibling)
429
        {
430
           element = element.nextSibling;
431
        }
432
        else
433
        {
434
          do
435
          {
436
            element = element.parentNode;
437
          }
438
          while (element && element!=parentElement && !element.nextSibling);
439
440
          if (element && element!=parentElement)
441
          {
442
            element = element.nextSibling;
443
          }
444
        }
445
      }
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
446
    };
447
448
    this.Toggle = function(id)
449
    {
450
      var element = this.FindChildElement(id);
451
      if (element)
452
      {
453
        if (element.style.display == 'block')
454
        {
455
          element.style.display = 'none';
456
        }
457
        else
458
        {
459
          element.style.display = 'block';
460
        }
461
      }
462
    };
463
464
    // Searches for the passed string.  If there is no parameter,
465
    // it takes it from the URL query.
466
    //
467
    // Always returns true, since other documents may try to call it
468
    // and that may or may not be possible.
469
    this.Search = function(search)
470
    {
471
      if (!search) // get search word from URL
472
      {
473
        search = window.location.search;
474
        search = search.substring(1);  // Remove the leading '?'
475
        search = unescape(search);
476
      }
477
478
      search = search.replace(/^ +/, ""); // strip leading spaces
479
      search = search.replace(/ +$/, ""); // strip trailing spaces
480
      search = search.toLowerCase();
481
      search = convertToId(search);
482
483
      var resultRows = document.getElementsByTagName("div");
484
      var matches = 0;
485
486
      var i = 0;
487
      while (i < resultRows.length)
488
      {
489
        var row = resultRows.item(i);
490
        if (row.className == "SRResult")
491
        {
492
          var rowMatchName = row.id.toLowerCase();
493
          rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
494
495
          if (search.length<=rowMatchName.length &&
496
             rowMatchName.substr(0, search.length)==search)
497
          {
498
            row.style.display = 'block';
499
            matches++;
500
          }
501
          else
502
          {
503
            row.style.display = 'none';
504
          }
505
        }
506
        i++;
507
      }
508
      document.getElementById("Searching").style.display='none';
509
      if (matches == 0) // no results
0 ignored issues
show
Best Practice introduced by
Comparing matches to 0 using the == operator is not safe. Consider using === instead.
Loading history...
510
      {
511
        document.getElementById("NoMatches").style.display='block';
512
      }
513
      else // at least one result
514
      {
515
        document.getElementById("NoMatches").style.display='none';
516
      }
517
      this.lastMatchCount = matches;
518
      return true;
519
    };
520
521
    // return the first item with index index or higher that is visible
522 View Code Duplication
    this.NavNext = function(index)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
523
    {
524
      var focusItem;
525
      while (1)
526
      {
527
        var focusName = 'Item'+index;
528
        focusItem = document.getElementById(focusName);
529
        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
530
        {
531
          break;
532
        }
533
        else if (!focusItem) // last element
534
        {
535
          break;
536
        }
537
        focusItem=null;
538
        index++;
539
      }
540
      return focusItem;
0 ignored issues
show
Comprehensibility Bug introduced by
The variable focusItem does not seem to be initialized in case the while loop on line 525 is not entered. Are you sure this can never be the case?
Loading history...
541
    };
542
543 View Code Duplication
    this.NavPrev = function(index)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
544
    {
545
      var focusItem;
546
      while (1)
547
      {
548
        var focusName = 'Item'+index;
549
        focusItem = document.getElementById(focusName);
550
        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
551
        {
552
          break;
553
        }
554
        else if (!focusItem) // last element
555
        {
556
          break;
557
        }
558
        focusItem=null;
559
        index--;
560
      }
561
      return focusItem;
0 ignored issues
show
Comprehensibility Bug introduced by
The variable focusItem does not seem to be initialized in case the while loop on line 546 is not entered. Are you sure this can never be the case?
Loading history...
562
    };
563
564
    this.ProcessKeys = function(e)
565
    {
566
      if (e.type == "keydown")
567
      {
568
        this.repeatOn = false;
569
        this.lastKey = e.keyCode;
570
      }
571
      else if (e.type == "keypress")
572
      {
573
        if (!this.repeatOn)
574
        {
575
          if (this.lastKey) this.repeatOn = true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
576
          return false; // ignore first keypress after keydown
577
        }
578
      }
579
      else if (e.type == "keyup")
580
      {
581
        this.lastKey = 0;
582
        this.repeatOn = false;
583
      }
584
      return this.lastKey!=0;
0 ignored issues
show
Best Practice introduced by
Comparing this.lastKey to 0 using the != operator is not safe. Consider using !== instead.
Loading history...
585
    };
586
587
    this.Nav = function(evt,itemIndex)
588
    {
589
      var e  = (evt) ? evt : window.event; // for IE
590
      if (e.keyCode==13) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
591
      if (!this.ProcessKeys(e)) return false;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
592
593
      if (this.lastKey==38) // Up
594
      {
595
        var newIndex = itemIndex-1;
596
        var focusItem = this.NavPrev(newIndex);
597
        if (focusItem)
598
        {
599
          var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
600
          if (child && child.style.display == 'block') // children visible
601
          {
602
            var n=0;
603
            var tmpElem;
604
            while (1) // search for last child
605
            {
606
              tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
607
              if (tmpElem)
608
              {
609
                focusItem = tmpElem;
610
              }
611
              else // found it!
612
              {
613
                break;
614
              }
615
              n++;
616
            }
617
          }
618
        }
619
        if (focusItem)
620
        {
621
          focusItem.focus();
622
        }
623
        else // return focus to search field
624
        {
625
           parent.document.getElementById("MSearchField").focus();
0 ignored issues
show
Bug introduced by
The variable parent seems to be never declared. If this is a global, consider adding a /** global: parent */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
626
        }
627
      }
628
      else if (this.lastKey==40) // Down
629
      {
630
        var newIndex = itemIndex+1;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable newIndex already seems to be declared on line 595. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
631
        var focusItem;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable focusItem already seems to be declared on line 596. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
632
        var item = document.getElementById('Item'+itemIndex);
633
        var elem = this.FindChildElement(item.parentNode.parentNode.id);
634
        if (elem && elem.style.display == 'block') // children visible
635
        {
636
          focusItem = document.getElementById('Item'+itemIndex+'_c0');
637
        }
638
        if (!focusItem) focusItem = this.NavNext(newIndex);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
639
        if (focusItem)  focusItem.focus();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
640
      }
641
      else if (this.lastKey==39) // Right
642
      {
643
        var item = document.getElementById('Item'+itemIndex);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable item already seems to be declared on line 632. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
644
        var elem = this.FindChildElement(item.parentNode.parentNode.id);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable elem already seems to be declared on line 633. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
645
        if (elem) elem.style.display = 'block';
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
646
      }
647
      else if (this.lastKey==37) // Left
648
      {
649
        var item = document.getElementById('Item'+itemIndex);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable item already seems to be declared on line 632. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
650
        var elem = this.FindChildElement(item.parentNode.parentNode.id);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable elem already seems to be declared on line 633. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
651
        if (elem) elem.style.display = 'none';
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
652
      }
653
      else if (this.lastKey==27) // Escape
654
      {
655
        parent.searchBox.CloseResultsWindow();
656
        parent.document.getElementById("MSearchField").focus();
657
      }
658
      else if (this.lastKey==13) // Enter
659
      {
660
        return true;
661
      }
662
      return false;
663
    };
664
665
    this.NavChild = function(evt,itemIndex,childIndex)
666
    {
667
      var e  = (evt) ? evt : window.event; // for IE
668
      if (e.keyCode==13) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
669
      if (!this.ProcessKeys(e)) return false;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
670
671
      if (this.lastKey==38) // Up
672
      {
673
        if (childIndex>0)
674
        {
675
          var newIndex = childIndex-1;
676
          document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
677
        }
678
        else // already at first child, jump to parent
679
        {
680
          document.getElementById('Item'+itemIndex).focus();
681
        }
682
      }
683
      else if (this.lastKey==40) // Down
684
      {
685
        var newIndex = childIndex+1;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable newIndex already seems to be declared on line 675. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
686
        var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
687
        if (!elem) // last child, jump to parent next parent
688
        {
689
          elem = this.NavNext(itemIndex+1);
690
        }
691
        if (elem)
692
        {
693
          elem.focus();
694
        }
695
      }
696
      else if (this.lastKey==27) // Escape
697
      {
698
        parent.searchBox.CloseResultsWindow();
0 ignored issues
show
Bug introduced by
The variable parent seems to be never declared. If this is a global, consider adding a /** global: parent */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
699
        parent.document.getElementById("MSearchField").focus();
700
      }
701
      else if (this.lastKey==13) // Enter
702
      {
703
        return true;
704
      }
705
      return false;
706
    }
707
}
708
709
function setKeyActions(elem,action)
710
{
711
  elem.setAttribute('onkeydown',action);
712
  elem.setAttribute('onkeypress',action);
713
  elem.setAttribute('onkeyup',action);
714
}
715
716
function setClassAttr(elem,attr)
717
{
718
  elem.setAttribute('class',attr);
719
  elem.setAttribute('className',attr);
720
}
721
722
function createResults()
723
{
724
  var results = document.getElementById("SRResults");
725
  for (var e=0; e<searchData.length; e++)
0 ignored issues
show
Bug introduced by
The variable searchData seems to be never declared. If this is a global, consider adding a /** global: searchData */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
726
  {
727
    var id = searchData[e][0];
728
    var srResult = document.createElement('div');
729
    srResult.setAttribute('id','SR_'+id);
730
    setClassAttr(srResult,'SRResult');
731
    var srEntry = document.createElement('div');
732
    setClassAttr(srEntry,'SREntry');
733
    var srLink = document.createElement('a');
734
    srLink.setAttribute('id','Item'+e);
735
    setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
736
    setClassAttr(srLink,'SRSymbol');
737
    srLink.innerHTML = searchData[e][1][0];
738
    srEntry.appendChild(srLink);
739
    if (searchData[e][1].length==2) // single result
740
    {
741
      srLink.setAttribute('href',searchData[e][1][1][0]);
742
      if (searchData[e][1][1][1])
743
      {
744
       srLink.setAttribute('target','_parent');
745
      }
746
      var srScope = document.createElement('span');
747
      setClassAttr(srScope,'SRScope');
748
      srScope.innerHTML = searchData[e][1][1][2];
749
      srEntry.appendChild(srScope);
750
    }
751
    else // multiple results
752
    {
753
      srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
754
      var srChildren = document.createElement('div');
755
      setClassAttr(srChildren,'SRChildren');
756
      for (var c=0; c<searchData[e][1].length-1; c++)
757
      {
758
        var srChild = document.createElement('a');
759
        srChild.setAttribute('id','Item'+e+'_c'+c);
760
        setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
761
        setClassAttr(srChild,'SRScope');
762
        srChild.setAttribute('href',searchData[e][1][c+1][0]);
763
        if (searchData[e][1][c+1][1])
764
        {
765
         srChild.setAttribute('target','_parent');
766
        }
767
        srChild.innerHTML = searchData[e][1][c+1][2];
768
        srChildren.appendChild(srChild);
769
      }
770
      srEntry.appendChild(srChildren);
771
    }
772
    srResult.appendChild(srEntry);
773
    results.appendChild(srResult);
774
  }
775
}
776
777
function init_search()
778
{
779
  var results = document.getElementById("MSearchSelectWindow");
780
  for (var key in indexSectionLabels)
0 ignored issues
show
Bug introduced by
The variable indexSectionLabels seems to be never declared. If this is a global, consider adding a /** global: indexSectionLabels */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
781
  {
782
    var link = document.createElement('a');
783
    link.setAttribute('class','SelectItem');
784
    link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
785
    link.href='javascript:void(0)';
786
    link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
787
    results.appendChild(link);
788
  }
789
  searchBox.OnSelectItem(0);
0 ignored issues
show
Bug introduced by
The variable searchBox seems to be never declared. If this is a global, consider adding a /** global: searchBox */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
790
}
791
792